<template xmlns:a-col="http://www.w3.org/1999/html">
  <a-layout style="overflow: scroll">
    <a-row>
      <!--聊天对象tag-->
      <a-col :span="4" style="background-color: #c8cacb; height: 550px; overflow: auto">
        <a-list item-layout="horizontal" :data-source="chatOptions">
          <template #renderItem="{ item }">
            <!--当前聊天对象-->
            <a-list-item @click="handleOption(item.targetId)" v-if="toId != null && toId === item.targetId"
                         style="background-color: #a69f9f;
                         text-overflow: ellipsis;
                         max-height: 60px;
                          overflow: hidden;
                          display: -webkit-box;
                          -webkit-line-clamp: 1;
                          -webkit-box-orient: vertical;">
              <a-list-item-meta
                  :description="item.lastMsg"
              >
                <template #title>
                  <a href="https://www.antdv.com/">{{ item.nickname }}</a>
                </template>
                <template #avatar>
                  <a-avatar :src="item.header" />
                </template>
              </a-list-item-meta>
            </a-list-item>
            <!--其他聊天对象-->
            <a-list-item @click="handleOption(item.targetId)" v-else
                         style="text-overflow: ellipsis;
                        max-height: 60px;
                        overflow: hidden;
                        display: -webkit-box;
                        -webkit-line-clamp: 1;
                        -webkit-box-orient: vertical;">
              <a-list-item-meta
                  :description="item.lastMsg"
              >
                <template #title>
                  <a href="https://www.antdv.com/">{{ item.nickname }}</a>
                </template>
                <template #avatar>
                  <a-badge v-if="item.unReadNum>0" :count="item.unReadNum">
                    <a-avatar :src="item.header" />
                  </a-badge>
                  <a-avatar v-else :src="item.header" />
                </template>
              </a-list-item-meta>
            </a-list-item>
          </template>
        </a-list>
      </a-col>
      <!--聊天主框-->
      <a-col :span="20" v-if="toId!=null">
        <a-col :span="24" v-if="currentTarget!==null">
          <!--展示聊天对象的基本信息-->
          <a-typography-title :level="4">
            {{currentTarget.nickname}}
          </a-typography-title>
        </a-col>
        <a-layout-content id="chat-box" style="height: 420px;overflow-y: auto;overflow-x: hidden">
          <a-row>
            <!--聊天框消息列表-->
            <a-col :span="24" v-for="msgItem in msgList" style="padding: 6px">
              <!--对方的消息展示-->
              <div v-if="msgItem.label==='target'" style="align-self: flex-start;flex-flow: row-reverse; text-align: left">
                <a-row style="text-align: left">
                  <a-col :span="1">
                    <a-avatar :src="msgItem.avatar"/>
                  </a-col>
                  <a-col :span="12">
                    <a-col :span="24">
                      <a-typography-text type="secondary">
                        {{msgItem.datetime}}
                      </a-typography-text>
                    </a-col>
                    <a-col :span="24">
                      <div class="bubble">
                        {{msgItem.content}}
                      </div>
                    </a-col>
                  </a-col>
                </a-row>
              </div>
              <!--自己的消息展示-->
              <div v-if="msgItem.label==='mine'" style="align-self: flex-end; flex-flow: column-reverse; text-align: right" >
                <a-row >
                  <a-col :span="11"/>
                  <a-col :span="12">
                    <a-col :span="24">
                      <a-typography-text type="secondary">
                        {{msgItem.datetime}}
                      </a-typography-text>
                    </a-col>
                    <a-col :span="24" style="align-self: flex-end;">
                      <div class="bubble">
                        {{msgItem.content}}
                      </div>
                    </a-col>
                  </a-col>
                  <a-col :span="1">
                    <a-avatar :src="msgItem.avatar"/>
                  </a-col>
                </a-row>
              </div>
            </a-col>
          </a-row>
        </a-layout-content>
        <!--文字发送框-->
        <a-layout-footer style="background-color: #909c9f; height: 110px; overflow: scroll; padding: 1px">
          <a-comment>
            <template #content>
              <a-row justify="space-around" align="middle">
                <a-col :span="20">
                  <a-form-item>
                    <a-textarea v-model:value="useSocketStore().sendMsgParam.msgContent" :rows="1" />
                  </a-form-item>
                </a-col>
                <a-col :span="4">
                  <a-form-item>
                    <a-button html-type="submit" type="primary" @click="sendMsg()">
                      发送
                    </a-button>
                  </a-form-item>
                </a-col>
              </a-row>
            </template>
          </a-comment>
        </a-layout-footer>
      </a-col>
    </a-row>
  </a-layout>
</template>

<script setup>
import {ref, watch, onBeforeMount, nextTick, onBeforeUnmount, reactive} from "vue";
import {useSocketStore} from "@/utils/websocket";
import router from "@/router";
import request from "@/utils/request";
import {message} from "ant-design-vue";

let session = JSON.parse(localStorage.getItem("session"))

// 聊天对象的缓存列表
let chatOptions = ref([])
// key:targetId, value: chatOptions_index
let chatOptionIndexMap = new Map()

// 当前聊天对象
let toId = ref(null)
let currentTarget = ref(null)

// 消息列表
let msgList = ref([])

// 监听ws的消息(聊天对象的消息)
watch(() => useSocketStore().msg, message => {
  // 私聊消息处理
  if (message.type === 1) {
    let index = chatOptionIndexMap.get(message.fromId);
    if(message.fromId === toId.value) {
      //消息来自当前聊天对象
      msgListAdd('target', currentTarget.value.nickname, currentTarget.value.header, message.msgContent,
          dateFormat(new Date(message.sendTime)))
    } else {
      // 消息来自其他聊天对象
      if (typeof index !== "undefined") {
        chatOptions.value[index].unReadNum++
      }
    }
    if (typeof index !== "undefined") {
      chatOptions.value[index].lastMsg = message.msgContent
    }
  }
})

// 监听聊天框的消息列表，滚动条跟随到最新消息
watch(()=>msgList.value, (val)=>{
  let chatBox = document.getElementById('chat-box')
  nextTick(()=>{
    chatBox.scrollTo(0, chatBox.scrollHeight - chatBox.clientHeight)
  })
},{
  deep: true,
  flush: 'post'
})

// 监听toId的变化
watch(() => toId.value, (value, old_val) => {
  if(typeof value !== "undefined" && value !== null) {
    useSocketStore().sendMsgParam.toId = value
    msgList.value = []
    // 获取聊天对象的基本信息和聊天消息记录
    request({
      url: '/im/member/get-targetInfo',
      method: 'post',
      data: {fromId: JSON.stringify(session.id), toId: value}
    }).then(res=>{
      console.log(res)
      if(res.code === 0){
        currentTarget.value = res.data.userInfo
        res.data.chatMsgList.forEach(item=>{
          if (item.fromId === JSON.stringify(session.id)) {
            // 自己的消息
            msgListAdd('mine', session.nickname, session.header, item.msgContent, dateFormat(new Date(item.sendTime)))
          } else {
            // 对方的消息
            let temp = res.data.userInfo
            msgListAdd('target', temp.nickname, temp.header, item.msgContent, dateFormat(new Date(item.sendTime)))
          }
        })
      }
    })

    // 确定接收到其消息
    ackMsg(JSON.stringify(session.id), value)
    nextTick(()=> {
      if(chatOptions.value.length > 0) {
        chatOptions.value[chatOptionIndexMap.get(value)].unReadNum = 0
      }
    })
  }
  if(typeof old_val !== "undefined") {
    // 将当前聊天对象的消息全部已读
    ackMsg(JSON.stringify(session.id), old_val)
  }
})

const ackMsg = (userId, targetId) => {
  request({
    url: `/im/chat-msg/ack-message/${userId}/${targetId}`,
    method: 'get'
  }).then(res=>{
    if(res.code !== 0) {
      console.log(res.msg)
      message.warn(res.msg)
    }
  })
}

onBeforeMount(_=>{
  toId.value = router.currentRoute.value.query.toId
  // 获取我所有的消息
  request({
    url: `/im/chat-msg/get-messages-list/${session.id}`,
    method: 'get'
  }).then(res => {
    console.log(res)
    if (res.code === 0) {
      chatOptions.value = []
      for (let i = 0; i < res.data.length; i++) {
        chatOptions.value.push(res.data[i])
        chatOptionIndexMap.set(res.data[i].targetId, i)
      }
    }
  }).catch(err=>{
    console.log('获取我的所有消息异常', err.message)
  })
})

onBeforeUnmount(_=>{
  if(typeof toId !== "undefined") {
    ackMsg(JSON.stringify(session.id), toId.value)
  }
})

const sendMsg =()=>{
  useSocketStore().sendMsgParam.type=1

  useSocketStore().sendMsg()
  // 添加自己的消息
  let date =  useSocketStore().sendMsgParam.sendTime
  let sendTime = dateFormat(date)
  msgListAdd('mine', session.nickname, session.header, useSocketStore().sendMsgParam.msgContent, sendTime)
  useSocketStore().sendMsgParam.msgContent = ''
}

/**
 * 切换聊天对象
 * @param targetId
 */
const handleOption =(targetId)=>{
  toId.value = targetId
}

const msgListAdd =(label, nickName, avatar, content, datetime)=>{
  msgList.value.push({label, nickName, avatar, content, datetime})
}

/**
 *
 * @param date new Date()类型
 * @returns yyyt-MM-dd HH:mm
 */
const dateFormat =(date)=>{
  return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, 0)}
                  -${(date.getDate()).toString().padStart(2, 0)} ${(date.getHours()).toString().padStart(2, 0)}
                  :${(date.getMinutes()).toString().padStart(2, 0)}`
}

</script>

<style>
.bubble {
  display: inline-block;
  background-color: #44e337;
  border-radius: 5px;
  padding: 10px;
  margin: 10px;
  text-align: left;
}

.bubble::after {
  content: '';
  position: absolute;
  bottom: -10px; /* 根据气泡的大小调整 */
  left: 50%;
  transform: translateX(-50%);
  border-width: 10px;
  border-style: solid;
  border-color: transparent transparent #f2f2f2 transparent;
}
</style>
